//Cuxhin、初心 
#include<bits/stdc++.h>
const int N = 1e6 + 10;
const int M = (1 << 20) + 10;
using namespace std;
int n, k, tt, a[N];
struct Node {
    int id, p;
    friend bool operator<(Node x, Node y) {
        return x.p < y.p;
    }
}ans[N];
//分别对应盒子数量，每个盒子里面多少个数，到下标i需要多少个盒子，入度，建图时是否遍历过，是否要放入盒子。
int maxbox, cnt[M], need_box[M], in[M], vis[M], st[M];
vector<int> edge[M];
queue<int> q;
signed main() {
    /*Init*/
    //解绑加快读入速度
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> k;
    for (int i = 1;i <= n;i++) {
        cin >> a[i], st[a[i]] = 1;
    }
    /*Build_Edge*/
    q.push(0);
    while (!q.empty()) {
        int u = q.front();q.pop();
        for (int i = 0;i < k;++i) {
            if (((u >> i) & 1) == 0) {
                int v = u | (1 << i);
                edge[u].push_back(v);
                ++in[v];
                if (!vis[v]) q.push(v), vis[v] = 1;
            }
        }
    }
    /*TopoSort*/
    q.push(0);
    while (!q.empty()) {
        int u = q.front();q.pop();
        if (st[u] == 1) {
            ++need_box[u];
            ans[++tt] = { u,need_box[u] };
            ++cnt[need_box[u]];
        }
        maxbox = max(maxbox, need_box[u]);
        for (int v : edge[u]) {
            --in[v];
            need_box[v] = max(need_box[v], need_box[u]);
            if (!in[v]) q.push(v);
        }
    }
    /*print*/
    sort(ans + 1, ans + 1 + n);
    cout << "1\n" << maxbox << '\n';
    for (int i = 1;i <= n;i++) {
        if (ans[i].p != ans[i - 1].p) cout << cnt[ans[i].p] << " ";
        cout << ans[i].id << " ";
        if (ans[i].p != ans[i + 1].p) cout << '\n';
    }
    return 0;
}
